package sanmubird.club.v8.FunctionParam.lambda;

import lombok.Data;
import org.junit.Test;

import java.util.concurrent.Callable;
import java.util.function.Predicate;

/**
 * 函数式接口
 * 就是只定义一个抽象方法的接口。
 * <p>
 * 你可能会想:
 * “为什么只有在需要函数式接口的时候才可以传递Lambda呢?”
 * 语言的设计者也考虑过其他办法,例如给Java添加函数类型(有点儿像我们介绍的描述Lambda表达式签名的特殊表示法)。
 * 但是他们选择了现在这种方式,因为这种方式自然且能避免语言变得更复杂。
 * <p>
 * 四大基本的函数式接口
 * Supplier 供给 Consumer 消费 Function 转换 Predicate 断言
 */
public class FunctionInterfaceDemo {

    @Test
    public void testAdvanced() {
        SmartAdder3 smartAdder3 = (aa, bb) -> aa + bb;
        int a = smartAdder3.add(1, 3);
        int b = smartAdder3.add(1.0d, 3.0d);
        System.out.println(a);
        System.out.println(b);
    }


    @Test
    public void testFunctionInterface() {
        // A
//        Adder adder = (aa, bb) -> aa + bb;

        // B
//        SmartAdder smartAdder = (n1, n2) -> n1+n2;

        // C
//        SmartAdder smartAdder = (int n1, int n2) -> n1+n2;

        // D
//        SmartAdder smartAdder = (d1, d2) -> Integer.valueOf(String.valueOf(d1 + d2));

        // E
//        SmartAdder smartAdder = (double d1, double d2) -> new Double(d1 + d2).intValue();

        // F
//        SmartAdder2 smartAdder2 = (aa, bb) -> aa + bb;
    }


    private void execute(Runnable r) {
        r.run();
    }

    // 方法签名 <V> () -> V
    public Callable<String> fetch() {
        return () -> "Tricky example ;-)";
    }

    @Test
    public void test() {
        // 方法签名 （） -> void
        execute(() -> {
        });

        // 方法签名 T t -> boolean
        Predicate<Apple> p = Apple::isSell;
    }
}

@Data
class Apple {
    String color;
    Double weight;
    String location;
    boolean isSell;
}

interface Adder {
    int add(int a, int b);
}

interface SmartAdder extends Adder {
    int add(double a, double b);
}

interface SmartAdder2 extends Adder {
    int add(int a, int b);
}

interface SmartAdder3 extends Adder {
    int add(int a, int b);

    default int add(double a, double b) {
        return 0;
    }
}

interface Nothing {

}


class SmartAdderImpl implements SmartAdder {

    @Override
    public int add(int a, int b) {
        return 0;
    }

    @Override
    public int add(double a, double b) {
        return 0;
    }
}

class SmartAdder2Impl implements SmartAdder2 {

    @Override
    public int add(int a, int b) {
        return 0;
    }
}